package nc.bs.levm.meampoundbill.rule;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import nc.bs.deliverynoticebill.apply.plugin.ApplyBillBPPluginPoint;
import nc.bs.framework.common.NCLocator;
import nc.impl.pubapp.pattern.data.bill.template.UpdateBPTemplate;
import nc.impl.pubapp.pattern.data.bill.tool.BillTransferTool;
import nc.itf.levmdeliverybill.bp.IDeliveryBillQueryService;
import nc.itf.levmdeliverybill.bp.IDeliveryBillService;
import nc.itf.mmgp.uif2.IMMGPCmnQueryService;
import nc.itf.uif.pub.IUifService;
import nc.util.mmf.framework.base.MMValueCheck;
import nc.vo.levmdeliverybill.deliverybill.AggDeliveryBillVO;
import nc.vo.levmdeliverybill.deliverybill.DeliveryBillBodyVO;
import nc.vo.levmdeliverybill.deliverybill.DeliveryBillHeadVO;
import nc.vo.levmmeampoundbill.poundbill.AggPoundBillVO;
import nc.vo.levmmeampoundbill.poundbill.PoundBillBVO;
import nc.vo.levmmeampoundbill.poundbill.PoundBillStatusEnum;
import nc.vo.levmmeampoundbill.poundbill.PoundBillVO;
import nc.vo.levmmeampoundbill.poundbill.ShippingStatusEnum;
import nc.vo.levmmeampoundbill.transtype.PoundTransTypeVO;
import nc.vo.levmprcstate.prcstateorder.PrcStateEnum;
import nc.vo.mmgp.util.MMStringUtil;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pubapp.pattern.pub.SqlBuilder;

public class UpdateDeliveryProcessStatusRule extends AbstractPoundRule {
	private boolean backward;

	public UpdateDeliveryProcessStatusRule(boolean backward) {
		this.backward = backward;
	}

	public void processPoundVO(AggPoundBillVO aggPoundVO) throws BusinessException {
		PoundBillVO poundHead = aggPoundVO.getParentVO();
		UFBoolean bloopcreate = poundHead.getBloopcreate();
		boolean tarevalid = tarevalid(poundHead);
		PoundBillBVO[] poundBodys = aggPoundVO.getChildrenVO();
		PrcStateEnum prcStateEnum = getRightState(poundHead, poundBodys);

		Set<String> deliveryIDs = new HashSet<String>();
		if (MMValueCheck.isEmpty(poundBodys))
			return;
		Map<String, Integer> nexcetimeMap = new HashMap<String, Integer>();
		for (PoundBillBVO pbVO : poundBodys) {
			if (!MMStringUtil.isEmpty(pbVO.getPk_delivery())) {
				deliveryIDs.add(pbVO.getPk_delivery());
				nexcetimeMap.put(pbVO.getPk_delivery_b(), pbVO.getNexecpoundcount());
			}
		}
		SqlBuilder whereSql = new SqlBuilder();
		if (MMValueCheck.isNotEmpty(deliveryIDs)) {
			whereSql.append("pk_delivery", (String[]) deliveryIDs.toArray(new String[0]));

			List<AggDeliveryBillVO> deliveryList = ((IDeliveryBillQueryService) NCLocator.getInstance()
					.lookup(IDeliveryBillQueryService.class)).queryDeliveryBillByWhereSql(whereSql.toString());
			IDeliveryBillService deliveryService = (IDeliveryBillService) NCLocator.getInstance()
					.lookup(IDeliveryBillService.class);

			List<AggDeliveryBillVO> aggDeliveryBillVOs = new ArrayList<AggDeliveryBillVO>();
			if (!this.backward) {
				for (AggDeliveryBillVO aggDelivery : deliveryList) {
					if (UFBoolean.TRUE.equals(bloopcreate)) {
						aggDelivery.getParentVO().setAttributeValue("biscompletemeam", UFBoolean.FALSE);
						aggDelivery.getParentVO().setAttributeValue("vprocessstatus",
								Integer.valueOf(PrcStateEnum.FIRST_MEASURE.toIntValue()));
						aggDeliveryBillVOs
								.add(deliveryService.checkBackwardState(aggDelivery, PrcStateEnum.FIRST_MEASURE));
						continue;
					}
					if (tarevalid) {
						aggDelivery.getParentVO().setAttributeValue("vprocessstatus",
								Integer.valueOf(PrcStateEnum.FIRST_MEASURE.toIntValue()));
					}
					aggDeliveryBillVOs.add(deliveryService.checkForwardState(aggDelivery, prcStateEnum));
				}

			} else {

				for (AggDeliveryBillVO aggDelivery : deliveryList) {
					DeliveryBillHeadVO deliveryHeadVO = aggDelivery.getParentVO();
					if (hasloopPound(aggDelivery.getPrimaryKey(), poundHead.getPk_poundbill())
							&& PrcStateEnum.FIRST_MEASURE.toIntValue() == deliveryHeadVO.getVprocessstatus()
									.intValue()) {
						deliveryHeadVO.setVprocessstatus(Integer.valueOf(PrcStateEnum.SECOND_MEASURE.toIntValue()));
						aggDeliveryBillVOs.add(aggDelivery);
						continue;
					}
					
				
					aggDeliveryBillVOs.add(deliveryService.checkBackwardState(aggDelivery, prcStateEnum));
				}
			}

			for (AggDeliveryBillVO aggDeliveryBillVO : aggDeliveryBillVOs) {
				aggDeliveryBillVO.getParentVO().setStatus(1);

				DeliveryBillBodyVO[] deliveryBodys = (DeliveryBillBodyVO[]) aggDeliveryBillVO.getAllChildrenVO();
				for (DeliveryBillBodyVO deliveryBody : deliveryBodys) {
					Integer exceTime = (Integer) nexcetimeMap.get(deliveryBody.getPk_delivery_b());
					deliveryBody.setNusedtimes((exceTime == null) ? null : (exceTime + ""));

					deliveryBody.setStatus(1);
				}
			}
			update((AggDeliveryBillVO[]) aggDeliveryBillVOs.toArray(new AggDeliveryBillVO[0]));
		}
	}

	private boolean hasloopPound(String pk_delivery, String pk_poundbill) throws BusinessException {
		String poundsql = " pk_poundbill IN( SELECT DISTINCT h.pk_poundbill FROM levm_poundbill h LEFT JOIN levm_poundbill_b b ON h.pk_poundbill = b.pk_poundbill WHERE b.pk_delivery = '"
				+ pk_delivery + "' AND isnull( h.dr, 0) = 0 AND isnull( b.dr, 0 ) = 0 and h.nbillstatus = "
				+ PoundBillStatusEnum.BILLSTATUS_COMPLETE.toIntValue() + " and h.bloopcreate = 'Y')";
		Object[] objs = ((IMMGPCmnQueryService) NCLocator.getInstance().lookup(IMMGPCmnQueryService.class))
				.cmnQueryDatasByCondition(AggPoundBillVO.class, poundsql);
		if (MMValueCheck.isEmpty(objs))
			return false;

		return Arrays.stream(objs).map(i -> (AggPoundBillVO) i).map(i -> i.getParentVO())
				.filter(i -> !i.getPk_poundbill().equals(pk_poundbill)).findAny().isPresent();
	}

	private PrcStateEnum getRightState(PoundBillVO poundHead, PoundBillBVO[] poundBodys) {
		PrcStateEnum prcStateEnum = PrcStateEnum.FIRST_MEASURE;

		for (PoundBillBVO body : poundBodys) {
			if (body.getNconfirmstatus() != null
					&& body.getNconfirmstatus().intValue() == ShippingStatusEnum.SHIPPING_HAS.toIntValue()) {
				prcStateEnum = PrcStateEnum.CHECK_AFTER_LOAD;
				break;
			}
		}
		if (poundHead.getNbillstatus() != null
				&& poundHead.getNbillstatus().intValue() == PoundBillStatusEnum.BILLSTATUS_COMPLETE.toIntValue()) {
			prcStateEnum = PrcStateEnum.SECOND_MEASURE;
		}
		if (this.backward) {
			prcStateEnum = (poundHead.getNbillstatus() != null
					&& poundHead.getNbillstatus().intValue() == PoundBillStatusEnum.BILLSTATUS_DELETE.toIntValue())
							? PrcStateEnum.FIRST_MEASURE
							: PrcStateEnum.SECOND_MEASURE;
		}
		return prcStateEnum;
	}

	private AggDeliveryBillVO[] update(AggDeliveryBillVO[] clientbills) {
		BillTransferTool<AggDeliveryBillVO> transTool = new BillTransferTool<AggDeliveryBillVO>(clientbills);

		AggDeliveryBillVO[] fullBills = (AggDeliveryBillVO[]) transTool.getClientFullInfoBill();

		AggDeliveryBillVO[] originBills = (AggDeliveryBillVO[]) transTool.getOriginBills();

		UpdateBPTemplate<AggDeliveryBillVO> bp = new UpdateBPTemplate<AggDeliveryBillVO>(ApplyBillBPPluginPoint.UPDATE);

		return (AggDeliveryBillVO[]) bp.update(fullBills, originBills);
	}

	private boolean tarevalid(PoundBillVO poundHeadVO) throws BusinessException {
		IMMGPCmnQueryService queryService = (IMMGPCmnQueryService) NCLocator.getInstance()
				.lookup(IMMGPCmnQueryService.class);

		String ctrantype = poundHeadVO.getCtrantypeid();
		Object[] poundTransTypeVOs = queryService.cmnQueryDatasByCondition(PoundTransTypeVO.class,
				"ctrantypeid='" + ctrantype + "'");

		boolean transtypeTareLimit = (boolean) ((poundTransTypeVOs != null && poundTransTypeVOs.length > 0
				&& ((PoundTransTypeVO) poundTransTypeVOs[0]).getBtarelimittime() != null)
						? ((PoundTransTypeVO) poundTransTypeVOs[0]).getBtarelimittime().booleanValue()
						: 0);
		UFDateTime now = new UFDateTime(new Date());
		Object[] vehicleVOs = queryService.cmnQueryDatasByCondition(nc.vo.levmvechile.vechile.AggVehicleVO.class,
				" vmainlicense='" + poundHeadVO.getVvehicle() + "' and " 
		       + " btarevalidctrl" + "='Y' and " + "ttarevalidtime" + " > '"+ now.toString()+ "'");

		boolean vehicleTareLimit = (vehicleVOs != null && vehicleVOs.length > 0);

		return (transtypeTareLimit && vehicleTareLimit);
	}

	public boolean isBackward() {
		return this.backward;
	}

	public void setBackward(boolean backward) {
		this.backward = backward;
	}
}
